package io.github.wanggit.antrpc.client.config.workers;

import io.github.wanggit.antrpc.IAntrpcContext;
import io.github.wanggit.antrpc.commons.config.ConfigChangeTypeEnum;
import io.github.wanggit.antrpc.commons.config.workers.IChangeWorker;
import io.github.wanggit.antrpc.commons.utils.CastValueTo;
import io.vavr.collection.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;

@Slf4j
public abstract class AbstractChangeWorker implements IChangeWorker {

    private final IAntrpcContext antrpcContext;

    private final List<String> prefixs;

    public AbstractChangeWorker(IAntrpcContext antrpcContext, List<String> prefixs) {
        this.antrpcContext = antrpcContext;
        this.prefixs = prefixs;
    }

    protected IAntrpcContext getAntrpcContext() {
        return antrpcContext;
    }

    protected List<String> getPrefixs() {
        return prefixs;
    }

    /**
     * 横线连接变量转驼峰命名法
     *
     * @param name report-argument-values
     * @return reportArgumentValues
     */
    protected String lineToCamel(String name) {
        if (name.contains("-")) {
            String[] tmps = name.split("-");
            for (int i = 1; i < tmps.length; i++) {
                tmps[i] = StringUtils.capitalize(tmps[i]);
            }
            return StringUtils.join(tmps);
        }
        return name;
    }

    protected String replacePrefixs(String key) {
        for (String prefix : getPrefixs()) {
            key = key.replace(prefix, "");
        }
        return key;
    }

    protected void setFieldValue(Object configObject, String key, String newValue) {
        key = replacePrefixs(key);
        if (log.isDebugEnabled()) {
            log.debug("Config Field = " + key);
        }
        // 如果是横线连接的，转为驼峰命名法
        String camelFieldName = lineToCamel(key);
        Field field = ReflectionUtils.findField(configObject.getClass(), camelFieldName);
        ReflectionUtils.makeAccessible(field);
        ReflectionUtils.setField(field, configObject, CastValueTo.cast(newValue, field.getType()));
    }

    @Override
    public void fired(
            ConfigChangeTypeEnum changeType, String key, String oldValue, String newValue) {
        if (log.isInfoEnabled()) {
            log.info(
                    "changeType="
                            + changeType.name()
                            + ", key="
                            + key
                            + ", oldValue="
                            + oldValue
                            + ", newValue="
                            + newValue);
        }
        if (ConfigChangeTypeEnum.DELETE.equals(changeType)) {
            if (log.isWarnEnabled()) {
                log.warn(key + " Not Worked when delete.");
            }
            return;
        }
        internalFired(changeType, key, oldValue, newValue);
    }

    protected abstract void internalFired(
            ConfigChangeTypeEnum changeType, String key, String oldValue, String newValue);
}
